#pragma once

#include <queue>
#include "common.h"

template <class T>
class CSafeQueue
{
public:
    CSafeQueue();
    ~CSafeQueue();
public:
    void Push(T t);
    void Pop(T& t);
private:
    std::queue<T> q_;
    pthread_mutex_t lock_;
    int capacity_;
    //生产者消费者队列
    pthread_cond_t consumer_;
    pthread_cond_t producer_;
};

template <class T>
CSafeQueue<T>::CSafeQueue()
{
    capacity_ = 1;
    pthread_mutex_init(&lock_, NULL);
    pthread_cond_init(&consumer_, NULL);
    pthread_cond_init(&producer_, NULL);
}

template <class T>
CSafeQueue<T>::~CSafeQueue()
{
    pthread_mutex_destroy(&lock_);
    pthread_cond_destroy(&consumer_);
    pthread_cond_destroy(&producer_);
}

template <class T>
void CSafeQueue<T>::Push(T t)
{
    pthread_mutex_lock(&lock_);
    
    while(q_.size() >= capacity_){
        pthread_cond_wait(&producer_, &lock_);
    }

    q_.push(t);
    std::cout << " i push "<<t<<std::endl;

    pthread_cond_signal(&consumer_);
    pthread_mutex_unlock(&lock_);
}

template <class T>
void CSafeQueue<T>::Pop(T& t)
{
    pthread_mutex_lock(&lock_);

    while(q_.empty()){
        pthread_cond_wait(&consumer_, &lock_);
    }

    t = q_.front();
    q_.pop();
    std::cout << " i pop "<<t<<std::endl;
    pthread_cond_signal(&producer_);
    pthread_mutex_unlock(&lock_);
}